package com.clsfd.ussd;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Console;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.CookieHandler;
import java.net.CookieManager;
import java.net.CookiePolicy;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Set;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;


import com.clsfd.charging.ChargeEvent;
import com.clsfd.charging.ChargeStatus;
import com.clsfd.database.ClassifiedItem;
import com.clsfd.database.DatabaseConnection;
import com.clsfd.database.SystemParams;
import com.clsfd.sms.SMSHandler;

public class UssdServerThread extends Thread{

	/**
	 * @param args
	 * @throws SQLException 
	 * @throws ClassNotFoundException 
	 * @throws FileNotFoundException 
	 * @throws IOException 
	 */
	String urlhistory[]= new String [30];
	String msisdn="";
	private CookieManager manager ;
	public  UssdServerThread(String msisdn, String ussdcode) throws FileNotFoundException, ClassNotFoundException, IOException, SQLException {
		
		this.msisdn=msisdn;
		manager = new CookieManager();
        manager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
        CookieHandler.setDefault(manager);
               
	}
	
	public void run(){
		
		
		urlhistory[0]="http://localhost:8080/smsreceiver/ussdreceiver?menuid=MainMenu&msisdn="+msisdn;
		int currentlevel=0;
		try {
			while(true)
			{
				UssdMenu ussdmsg = getUSSDMessage(urlhistory[currentlevel]);
				if (ussdmsg.getAction().equalsIgnoreCase("ShowMenu")){
					int resp=showInteractiveMenu(ussdmsg.getHeading(),ussdmsg.getMenuItem(), ussdmsg.getHasHome(), ussdmsg.getHasBack(), ussdmsg.getNomatch());
					if( resp==98){		// Go Back							
						currentlevel--;
					}
					else if( resp==99){		// Go Home							
						currentlevel=0;
					}
					else{			
						currentlevel++;
						urlhistory[currentlevel]=ussdmsg.getMenuItem()[resp].getUrl().replaceAll("%MSISDN%", msisdn);
					}
				}
				else if (ussdmsg.getAction().equalsIgnoreCase("Notification")){
					System.out.println(ussdmsg.getHeading());
					break;
				}
				else if (ussdmsg.getAction().equalsIgnoreCase("GetUserInput")){
					while(true){
						Boolean invalidinput=false;
						String ussdString=invalidinput?ussdmsg.getNomatch():ussdmsg.getInput().getText();
						ussdString+= ussdmsg.getHasBack()?"\n*.Back":"";
						ussdString+= ussdmsg.getHasHome()?"\n#.Home":"";
						String resp= getResponse(ussdString);
						if( ussdmsg.getHasBack()&&resp.equals("*")){		// Go Back							
							currentlevel--;
						}
						else if( ussdmsg.getHasHome()&&resp.equals("#*")){		// Go Home							
							currentlevel=0;
						}
						else if(ussdmsg.getInput().getType().equalsIgnoreCase("Number") && isInteger(resp) && Integer.parseInt(resp)<=ussdmsg.getInput().getmax() && Integer.parseInt(resp)>= ussdmsg.getInput().getmin()){		// get a Number
							currentlevel++;							
							urlhistory[currentlevel]=ussdmsg.getInput().getUrl().replaceAll("%MSISDN%", msisdn).replaceAll("%ASIGN%$", resp);
						}
						else if(ussdmsg.getInput().getType().equalsIgnoreCase("alphanum") && resp.length()<=ussdmsg.getInput().getmax() && resp.length()>= ussdmsg.getInput().getmin()){		// get a Number
							currentlevel++;							
							urlhistory[currentlevel]=ussdmsg.getInput().getUrl().replaceAll("%MSISDN%", msisdn).replaceAll("%ASIGN%$", resp);
						}
						else{
							invalidinput=true;
						}
					}
				}
			}
		} catch (IllegalStateException | IOException | JAXBException e) {
			e.printStackTrace();
		}
	}
	
	
	
	
	public static void main(String[] args) throws IOException, ClassNotFoundException, SQLException, IllegalStateException, JAXBException {
		UssdServerThread ussd = new UssdServerThread("94722241035","#111#");	
		ussd.start();
	}
	
	private  UssdMenu getUSSDMessage(String urlstring) throws IOException, IllegalStateException, JAXBException {
		
		URL url = new URL(urlstring);
        URLConnection connection = url.openConnection();
        InputStream is=  connection.getInputStream();
		return UssdMenu.decode( is);
		
		
	}


	public String getResponse(String msg) throws IOException{
		System.out.println(msg+"\n");
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		return br.readLine();
	}
	
	
	public int showInteractiveMenu(String heading, UssdMenuItem []items, Boolean showHome, Boolean showBack, String nomatch) throws IOException{
		
		String msg="";
		showHome=showHome==null?false:showHome;
		showBack=showBack==null?false:showBack;
		int curliststart=0, curlistend=0, i=0;
		int maxlength=130;
		Boolean forward=true;
		Boolean invalidInput=false;
		createmenu:
		while (true) {
			if ( i>=0 && i<items.length && (msg.length()+items[i].getText().length()+2+Integer.toString(i+1).length())+(invalidInput?nomatch.length():heading.length())<maxlength){
				msg=forward?msg+"\n"+(i+1)+"."+items[i].getText():"\n"+(i+1)+"."+items[i].getText()+msg;
				i=i+ (forward?1:-1);
			}else{
				curlistend=forward?--i:curlistend;
				curliststart=forward?curliststart:++i;
				msg+=i<items.length-1?"\n97.More":"";
				msg+=(showBack ||curliststart>0)?"\n98.Back":"";
				msg+=showHome?"\n99.Home":"";
				if (invalidInput){
					msg=nomatch+msg;
					invalidInput=false;
				}
				else{
					msg=heading+msg;
				}
				while(true)
				{
					String resp=getResponse( msg);
					if (isInteger(resp) && Integer.parseInt(resp)-1<=curlistend &&Integer.parseInt(resp)-1>=curliststart){
						return Integer.parseInt(resp)-1;
					}
					else if (curliststart>0 && resp.equals("98")){ // go back within the menu
						msg="";
						curliststart--;
						i=curliststart;
						curlistend=curliststart;
						forward=false;
						continue createmenu;
					}
					else if (curliststart==0 && showBack&& resp.equals("98")){
						return 98;	// go to the previous menu
					}
					else if (showHome && resp.equals("99")){
						return 99;	// go to the Home menu
					}
					else if (i<items.length && resp.equals("97")){ 
						msg="";
						curliststart=curlistend+1;
						i=curliststart;
						forward=true;
						continue createmenu;
					}
					else {
						i=curliststart;
						msg="";
						invalidInput=true;
						continue createmenu;
					}
				}
			}
		}
	}
	
    public boolean isInteger( String input )  
    {  
       try  
       {  
          Integer.parseInt( input );  
          return true;  
       }  
       catch( Exception e )  
       {  
          return false;  
       }  
    }  
}
